----------------------------------------
-- 微信小程序分享
-- 微信小程序分享-分享有礼
-- 微信小程序分享-邀请奖励
-- 微信小程序分享-邀请排名

-- db.plShare.shareCnt          -- 分享次数
-- db.plShare.shareAccounts     -- 分享账号列表
-- db.plShare.firstFlag         -- 首次分享状态 
-- db.plShare.rewardFlags       -- 奖励领取标记
-- db.plShare.groupCnt          -- 朋友圈今日分享次数
-- db.plShare.groupTime         -- 最近一次朋友圈分享时间
-- db.plShare.groupRewardCnt    -- 朋友圈分享可领取奖励次数

-- board.time                   -- 周一0点
-- board.list                   -- [uuid] = {uuid, cnt, accounts, time}
----------------------------------------

local PresentExcel = require("excel.present")
local MailExcel = require("excel.mail")
local Log = require("common.Log")
local Util = require("common.Util")
local CommonDB = require("common.CommonDB")
local Lang = require("common.Lang")
local Timer = require("core.Timer")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local Broadcast = require("broadcast.Broadcast")
local PanelDefine = require("broadcast.PanelDefine")
local MailManager = require("mail.MailManager")
local PfLogic = require("platform.PfLogic")
local RoleLogic = require("role.RoleLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local GuideLogic = require("guide.GuideLogic")

BOARD_SHARECNT_MAX = 100        -- 排行榜最高分享次数

FIRST_STATE_NONE = 0            -- 未分享
FIRST_STATE_HAD = 1             -- 已领取

REWARD_STATE_NONE = 0           -- 不可领
REWARD_STATE_GET = 1            -- 可领
REWARD_STATE_HAD = 2            -- 已领取

RANK_2_BOARDRANKDATA = RANK_2_BOARDRANKDATA or nil 

-- 是否开启
function isOpen(human, _, funcConfig)
    -- 不是以下平台不开放
    if not PfLogic.isKunTang() and 
        not PfLogic.isFKW() then
        return
    end

    -- 完成后活动要消失
    if human and funcConfig then
        if funcConfig.panelID == PanelDefine.PANEL_ID_148 then
            return isOpenFirst(human)
        end    
        if funcConfig.panelID == PanelDefine.PANEL_ID_149 then
            return isOpenReward(human)
        end
        if funcConfig.panelID == PanelDefine.PANEL_ID_151 then
            return isOpenGroup(human)
        end
    end
    return true
end

-- 分享有礼 
function isOpenFirst(human)
    if getFirstState(human) == FIRST_STATE_HAD then
        return
    end
    return true
end

-- 邀请奖励
function isOpenReward(human)
    do return true end
    for id in ipairs(PresentExcel.sharePFReward) do
        if not isGetReward(human, id) then
            return true
        end
    end
end

-- 朋友圈
function isOpenGroup(human)
    if human.isIOS == 1 then
        return -- ios不显示分享
    end
    return true
end

-- 红点
function isRed(human, _, funcConfig)
    if human and funcConfig then
        if funcConfig.panelID == PanelDefine.PANEL_ID_149 then
            return isRedReward(human)
        end
        if funcConfig.panelID == PanelDefine.PANEL_ID_151 then
            return isRedGroup(human)
        end
    end    
end

-- 邀请奖励红点
function isRedReward(human)
    for id in ipairs(PresentExcel.sharePFReward) do
        local state = getRewardState(human, id)
        if state == REWARD_STATE_NONE then
            break
        end
        if state == REWARD_STATE_GET then
            return true
        end
    end    
end

-- 朋友圈分享红点
function isRedGroup(human)
    if not isOpenGroup(human) then
        return
    end
    if getGroupRewardCnt(human) > 0 then
        return true
    end
end

-- 邀请奖励最大邀请人数
local REWARD_SHARECNT_MAX = nil
function getRewardShareCntMax()
    if not REWARD_SHARECNT_MAX then
        REWARD_SHARECNT_MAX = 0
        for _, cf in ipairs(PresentExcel.sharePFReward) do
            if cf.need > REWARD_SHARECNT_MAX then
                REWARD_SHARECNT_MAX = cf.need
            end
        end
    end
    return REWARD_SHARECNT_MAX
end

-- 获取排行榜刷新时间
function getBoardTime()
    return Util.getWeekStartTime(os.time())
end

-- 获取刷新剩余时间
local BOARD_KEEPTIME = 86400 * 7
function getBoardLeftTime()
    local startTime = getBoardTime()
    return getBoardTime() + BOARD_KEEPTIME - os.time()
end

------------------------------------ db -------------------------------------------
-- 获取分享有礼状态
function getFirstState(human)
    if not human.db.plShare then
        return FIRST_STATE_NONE
    end
    if not human.db.plShare.firstFlag then
        return FIRST_STATE_NONE
    end
    return human.db.plShare.firstFlag 
end

-- 设置分享有礼状态
function setFirstState(human, state)
    if not human.db.plShare then
        human.db.plShare = {}
    end
    human.db.plShare.firstFlag = state
end

-- 刷新分享人数
function setShareAccount(db, account)
    if not account then return end
    if account == "" then return end

    if not db.plShare then
        db.plShare = {}
    end
    local plShare = db.plShare
    plShare.shareAccounts = plShare.shareAccounts or {}
    plShare.shareCnt = plShare.shareCnt or 0
    if plShare.shareCnt >= getRewardShareCntMax() then
        return
    end
    if plShare.shareAccounts[account] then
        return
    end
    plShare.shareAccounts[account] = true
    plShare.shareCnt = plShare.shareCnt + 1
    return true
end

-- 获取已分享人数
function getShareCnt(human)
    if not human.db.plShare then
        return 0
    end
    return human.db.plShare.shareCnt or 0
end

-- 是否领取邀请奖励
function isGetReward(human, id)
    if not human.db.plShare then
        return 
    end 
    local rewardFlags = human.db.plShare.rewardFlags
    if not rewardFlags then return end   
    return Util.getBit(rewardFlags, id) > 0
end

-- 设置领取邀请奖励
function setGetReward(human, id)
    if not human.db.plShare then
        human.db.plShare = {}
    end
    local plShare = human.db.plShare
    plShare.rewardFlags = plShare.rewardFlags or 0
    plShare.rewardFlags = Util.setBit(plShare.rewardFlags, id)
end

-- 获取奖励状态
function getRewardState(human, id)
    local cf = PresentExcel.sharePFReward[id]
    if not cf then
        return REWARD_STATE_NONE
    end
    if getShareCnt(human) < cf.need then
        return REWARD_STATE_NONE
    end
    if isGetReward(human, id) then
        return REWARD_STATE_HAD
    end
    return REWARD_STATE_GET
end


--== 下面是排行榜db相关
-- 比较排名
local function cmpRank(a, b)
    if a.cnt ~= b.cnt then
        return a.cnt > b.cnt 
    end
    if a.time ~= b.time then
        return a.time < b.time
    end
    if a.rank and b.rank then
        return a.rank < b.rank
    end
    if a.rank or not b.rank then
        return true
    end
    return false
end

-- 排序
local function sortBoard(data, noSave)
    RANK_2_BOARDRANKDATA = RANK_2_BOARDRANKDATA or {}
    Util.cleanTable(RANK_2_BOARDRANKDATA)
    for uuid, rankData in pairs(data.list) do
        RANK_2_BOARDRANKDATA[#RANK_2_BOARDRANKDATA + 1] = rankData
    end
    if #RANK_2_BOARDRANKDATA > 1 then
        table.sort(RANK_2_BOARDRANKDATA, cmpRank)
    end
    local isChange = nil 
    for i = 1, #RANK_2_BOARDRANKDATA do
        local rankData = RANK_2_BOARDRANKDATA[i]
        if rankData.rank ~= i then
            rankData.rank = i
            isChange = true
        end
    end
    if isChange and not noSave then
        CommonDB.updateValue(CommonDB.KEY_SHARE_PLATFORM_BOARD, data)
    end
end

-- 排行榜
function getBoardList()
    local data = CommonDB.getValueByKey(CommonDB.KEY_SHARE_PLATFORM_BOARD)
    if not data or not data.list then
        return
    end
    if not RANK_2_BOARDRANKDATA then
        sortBoard(data)
    end
    return RANK_2_BOARDRANKDATA
end

-- 根据uuid获取个人数据
function getBoardRankData(uuid)
    local data = CommonDB.getValueByKey(CommonDB.KEY_SHARE_PLATFORM_BOARD)
    if not data or not data.list then
        return
    end
    return data.list[uuid]    
end

-- 重置排行榜
function resetBoard()
    local boardList = getBoardList()

    -- 先清
    local newData = {}
    newData.time = getBoardTime()
    newData.list = {}
    CommonDB.updateValue(CommonDB.KEY_SHARE_PLATFORM_BOARD, newData)

    -- 后发之前奖励
    local mailConfig = MailExcel.mail[104]
    local title = mailConfig.title
    local senderName = mailConfig.senderName    
    for _, config in ipairs(PresentExcel.sharePFBoard) do
        for rank = config.minRank, config.maxRank do
            local rankData = boardList and boardList[rank]
            if not rankData then break end
            local content = Util.format(mailConfig.content, rank)
            MailManager.add(MailManager.SYSTEM, rankData.uuid, title, content, config.reward, senderName)
        end
    end
    RANK_2_BOARDRANKDATA = nil
    return newData
end

-- 初始化上榜数据
local function initBoardRankData(uuid)
    local rankData = {}
    rankData.uuid = uuid
    rankData.cnt = 0
    rankData.accounts = {}
    rankData.time = nil
    rankData.rank = nil
    return rankData
end

-- 刷新排行榜
function updateBoard(uuid, account)
    if not account or account == "" then return end

    local data = CommonDB.getValueByKey(CommonDB.KEY_SHARE_PLATFORM_BOARD)   
    if not data or data.time ~= getBoardTime() then
        data = resetBoard()
    end

    if not data.list[uuid] then
        data.list[uuid] = initBoardRankData(uuid)
    end
    local rankData = data.list[uuid]
    if rankData.accounts[account] then
        return -- 分享过了
    end
    if rankData.cnt >= BOARD_SHARECNT_MAX then
        return -- 达到分享上限
    end

    rankData.time = os.time()
    rankData.cnt = rankData.cnt + 1
    rankData.accounts[account] = 1
    sortBoard(data, true)
    CommonDB.updateValue(CommonDB.KEY_SHARE_PLATFORM_BOARD, data)
    return true
end

-- 朋友圈已分享次数
function getGroupShareCnt(human)
    if not human.db.plShare then
        return 0
    end
    return human.db.plShare.groupCnt or 0
end

-- 朋友圈分享冷却CD
function getGroupCoolTime(human)
    if not human.db.plShare then
        return 0
    end
    if not human.db.plShare.groupTime then
        return 0
    end

    local leftTime = human.db.plShare.groupTime - os.time()
    return math.max(leftTime, 0)
end

-- 添加分享次数
function addGroupShareCnt(human)
    if not human.db.plShare then
        human.db.plShare = {}
    end
    local plShare = human.db.plShare
    plShare.groupCnt = (plShare.groupCnt or 0) + 1
    plShare.groupRewardCnt = (plShare.groupRewardCnt or 0) + 1
    plShare.groupTime = os.time() + PresentExcel.sharePFGroup[1].shareCD
end

-- 朋友圈分享可领取奖励次数
function getGroupRewardCnt(human)
    if not human.db.plShare then
        return 0
    end
    return human.db.plShare.groupRewardCnt or 0   
end

-- 清空朋友圈可领取次数
function clGroupRewardCnt(human)
    if not human.db.plShare then
        return 
    end
    human.db.plShare.groupRewardCnt = nil
end

------------------------------------ msg ------------------------------------------------

-- 查询分享有礼
function sendFirstQuery(human)
    if not (isOpen() and isOpenFirst(human)) then
        return
    end

    local config = PresentExcel.sharePFReward[1] 
    local msgRet = Msg.gc.GC_SHARE_PLATFORM_FIRST_QUERY
    msgRet.state = getFirstState(human)
    msgRet.rewards[0] = #config.firstReward
    for i = 1, msgRet.rewards[0] do
        local itemID = config.firstReward[i][1]
        local itemCnt = config.firstReward[i][2]
        Grid.makeItem(msgRet.rewards[i], itemID, itemCnt)
    end
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 分享弹窗
function sendFirstTip(human)
    if not (isOpen() and isOpenFirst(human)) then
        return
    end

    -- 未完全指定指引，不弹出
    if not GuideLogic.isFinishGuideID(human, 150) then
        return
    end

    local config = PresentExcel.sharePFReward[1] 
    local msgRet = Msg.gc.GC_SHARE_PLATFORM_FIRST_TIP
    msgRet.rewards[0] = #config.firstReward
    for i = 1, msgRet.rewards[0] do
        local itemID = config.firstReward[i][1]
        local itemCnt = config.firstReward[i][2]
        Grid.makeItem(msgRet.rewards[i], itemID, itemCnt)
    end
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)    
end

-- 分享完成
function shareInvate(human)
    if not isOpen() then return end

    local state = getFirstState(human)
    if state == FIRST_STATE_HAD then
        return
    end

    setFirstState(human, FIRST_STATE_HAD)
    ObjHuman.save(human)

    local mailConfig = MailExcel.mail[103]
    local title = mailConfig.title
    local senderName = mailConfig.senderName
    local content= mailConfig.content

    local config = PresentExcel.sharePFReward[1] 
    MailManager.add(MailManager.SYSTEM, human.db._id , title, content, config.firstReward, senderName)
    YunYingLogic.sendGroupList(human, PanelDefine.PANEL_ID_147)
    sendFirstQuery(human)
    Log.writeShareLog(human, 1)
end

-- 邀请奖励查询
function sendRewardQuery(human)
    if not (isOpen() and isOpenReward(human)) then 
        return 
    end  

    local msgRet = Msg.gc.GC_SHARE_PLATFORM_REWARDS_QUERY
    msgRet.nowValue = getShareCnt(human)
    msgRet.list[0] = #PresentExcel.sharePFReward
    for i = 1, msgRet.list[0] do
        local cf = PresentExcel.sharePFReward[i]
        local net = msgRet.list[i]
        net.id = i 
        net.needValue = cf.need
        net.state = getRewardState(human, i)
        net.rewards[0] = #cf.reward
        for j = 1, net.rewards[0] do
            local itemID = cf.reward[j][1]
            local itemCnt = cf.reward[j][2]
            Grid.makeItem(net.rewards[j], itemID, itemCnt)
        end
    end
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 领取邀请奖励
function getReward(human, id)
    if not isOpen() then return end

    local cf = PresentExcel.sharePFReward[id]
    if not cf then return end

    local state = getRewardState(human, id)
    if state == REWARD_STATE_NONE then
        return Broadcast.sendErr(human, Lang.YUNYING_GET_ERR_CONDITION)
    end
    if state == REWARD_STATE_HAD then
        return Broadcast.sendErr(human, Lang.YUNYING_GET_ERR_HADGET)
    end

    setGetReward(human, id)
    BagLogic.addItemList(human, cf.reward, "share_platform")
    
    if isOpenReward(human) then
        sendRewardQuery(human)        
        for k, v in pairs(funcID) do
            YunYingLogic.updateIcon(YYInfo[k], human)
	        YunYingLogic.sendGroupUpdate(YYInfo[k], human, PanelDefine.PANEL_ID_149)
            break
        end
    else
        for k, v in pairs(funcID) do
            YunYingLogic.updateIcon(YYInfo[k], human)
	        YunYingLogic.sendGroupUpdate(YYInfo[k], human, PanelDefine.PANEL_ID_147)
            break
        end
    end
end

-- 封装排行榜结构体
local function fontBoardNet(net, uuid, data)
    net.rank = data and data.rank or 0
    RoleLogic.getRoleBaseByUuid(uuid, net.roleBase)
    net.value = data and data.cnt or 0
end

-- 邀请排名查询
function sendBoard(human)
    if not isOpen() then return end

    local boardList = getBoardList()
    local msgRet = Msg.gc.GC_SHARE_PLATFORM_BOARD_QUERY
    msgRet.leftTime = getBoardLeftTime()
    msgRet.list[0] = math.min(boardList and #boardList or 0, #msgRet.list)
    for i = 1, msgRet.list[0] do
        local rankData = boardList[i]
        fontBoardNet(msgRet.list[i], rankData.uuid, rankData)
    end
    local myRankData = getBoardRankData(human.db._id)
    fontBoardNet(msgRet.myData, human.db._id, myRankData)
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 邀请排名奖励查询
function sendBoardReward(human)
    if not isOpen() then return end

    local msgRet = Msg.gc.GC_SHARE_PLATFORM_BOARD_REWARD
    msgRet.list[0] = #PresentExcel.sharePFBoard
    for i = 1, msgRet.list[0] do
        local net = msgRet.list[i]
        local cf = PresentExcel.sharePFBoard[i]
        net.minRank = cf.minRank
        net.maxRank = cf.maxRank
        net.rewards[0] = #cf.reward
        for j = 1, net.rewards[0] do
            local itemID = cf.reward[j][1]
            local itemCnt = cf.reward[j][2]
            Grid.makeItem(net.rewards[j], itemID, itemCnt) 
        end
    end
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 朋友圈分享界面查看
function sendGroupQuery(human)
    if not isOpen() then return end

    ObjHuman.updateDaily(human)

    local groupConfig = PresentExcel.sharePFGroup[1]
    local msgRet = Msg.gc.GC_SHARE_PLATFORM_GROUP_QUERY
    msgRet.rewards[0] = #groupConfig.rewards
    for i = 1, msgRet.rewards[0] do
        local itemID = groupConfig.rewards[i][1]
        local itemCnt = groupConfig.rewards[i][2]
        Grid.makeItem(msgRet.rewards[i], itemID, itemCnt)
    end
    msgRet.maxCnt = groupConfig.dailyCnt
    msgRet.nowCnt = getGroupShareCnt(human)
    msgRet.leftTime = getGroupCoolTime(human)
    msgRet.state = (getGroupRewardCnt(human) > 0) and 1 or 0
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 领取朋友圈奖励
function getGroupReward(human)
    if not isOpen() then return end

    local cnt = getGroupRewardCnt(human)
    if cnt < 1 then
        return Broadcast.sendErr(human, Lang.SHARE_GROUP_GET_ERR_CNT)
    end

    clGroupRewardCnt(human)
    local groupConfig = PresentExcel.sharePFGroup[1] 
    BagLogic.addItemList(human,groupConfig.rewards, "share_platform")
    sendGroupQuery(human)
    for k, v in pairs(funcID) do
        YunYingLogic.updateIcon(YYInfo[k], human)
	    YunYingLogic.sendGroupUpdate(YYInfo[k], human, PanelDefine.PANEL_ID_151)
        break
    end
end

-- 朋友圈分享成功
function groupShareOK(human)
    if not isOpen() then return end
    if not isOpenGroup(human) then return end

    local groupConfig = PresentExcel.sharePFGroup[1]
    if getGroupShareCnt(human) >= groupConfig.dailyCnt then
        return -- 每日次数上限
    end
    if getGroupCoolTime(human) > 0 then
        return -- cd中
    end

    addGroupShareCnt(human)
    for k, v in pairs(funcID) do
        YunYingLogic.updateIcon(YYInfo[k], human)
        break
    end
    sendGroupQuery(human)
    Log.writeShareLog(human, 2)
end

-----------------------------------------------------------------------------------
-- 到点发奖
function onZero()
    if _G.is_middle == true then
        return
    end
    if not isOpen() then return end
    
    local data = CommonDB.getValueByKey(CommonDB.KEY_SHARE_PLATFORM_BOARD)   
    if not data then return end
    if data.time == getBoardTime() then
        return
    end

    Timer.addLater(1, resetBoard)
    --resetBoard() 
end

-- 登陆
function onLogin(human)
    sendFirstTip(human)
end

-- 每日刷新
function updateDaily(human)
    if not human.db.plShare then
        return 
    end

    human.db.plShare.groupCnt = nil
end

-- 分享成功回调 后台
-- accountA是分享
-- accountB是点链接
-- 同一个账号一秒内收到太多回调怀疑是外挂
local ACCOUNT_2_SHARETIME = {}
local ACCOUNT_2_SHARECNT = {}
function onShareOk(accountA, accountB, nocheck)
    if not isOpen() then return end
    if not accountA or not accountB then
        return
    end
    if accountA == accountB then
        return
    end
    local nowTime = os.time()
    if ACCOUNT_2_SHARETIME[accountA] ~= nowTime then
        ACCOUNT_2_SHARETIME[accountA] = nowTime
        ACCOUNT_2_SHARECNT[accountA] = 0
    end
    ACCOUNT_2_SHARECNT[accountA] = ACCOUNT_2_SHARECNT[accountA] + 1
    if not nocheck and ACCOUNT_2_SHARECNT[accountA] > 5 then
        return -- 防刷！！
    end
    local db = RoleDBLogic.getDbByAccount(accountA)
    if not db then return end

    -- 个人分享奖励
    if setShareAccount(db, accountB) then
        RoleDBLogic.saveRole(db)
        local human = ObjHuman.onlineAccount[accountA]
        if human and human.fd then
            for k, v in pairs(funcID) do
                YunYingLogic.updateIcon(YYInfo[k], human)
                break
            end
        end
    end
    
    -- 分享排行榜
    updateBoard(db._id, accountB)
    return true
end
